package com.solarroast.mirrorarray.util;

import java.util.Calendar;
import java.util.GregorianCalendar;

import javax.swing.JLabel;

public class Clock implements Runnable {			
	double year;
	double month;
	double date;
	double hour;
	double minute;
	double second;
	double timeZone = -4;
	double timefraction;
    
	double latitude = 40;
	double longitude = -105;
	
	double jDN_noDate;
	double jA;
	double jY;
	double jM;
	double jD;
	double jDN;
	double jCent;
    
	double geomMeanLong;
	double geomMeanAnom;
	double eccentEarthOrbit;	// Eccent Earth Orbit
	double sunEqCtr;			// Sun Eq of Ctr
	double sunTrueLong;			// Sun True Long
	double sunTrueAnom;			// Sun True Anom
	double sunRadVector;		// Sun Rad Vector (AUs)
	double sunAppLong;			// Sun App Long (deg)
	double meanObliqEclip;		// Mean Obliq Ecliptic
	double obliqCorr;			// Obliq Corr (deg)
	double sunRtAscen;			// Sun Rt Ascen (deg)
	double sunDecline;			// Sun Decline (deg)
	double varY = 99;			// Var Y
	double eqOfTime;			// Eq of Time (minutes)
	double haSunrise;			// HA Sunrise (deg)
	double solarNoon;			// solarNoon (LST)
	double sunriseTime;			// Sunrise Time (LST)
	double sunsetTime;			// Sunset Time (LST)
	double sunlightDur;			// Sunlight Duration (minutes)
	double trueSolarTime;		// True Solar Time (minutes)
	double hourAngle;			// Hour Angle (deg)
	double solarZenithAngle;	// Solar Zenith Angle (deg) - OUTPUT 1
	double solarElevAngle;		// Solar Elevation Angle (deg) - OUTPUT 2
	
	Calendar now;
	
	public Clock() {
		now = Calendar.getInstance();
		initializeJulianDate();
	}
	
	public void run() {
		while(true) {
			//clock.setText(prefix + " " + getTime() + " " + postfix);
			now = Calendar.getInstance();
			jDN = getJulianDate();
			jCent = (jDN - 2451545.0) / 36525;
								
			if(second % 2 == 0) {
				geomMeanLong = (280.46646 + jCent * (36000.76983 + (jCent * 3.032E-4))) % 360;
				geomMeanAnom = 357.52911 + jCent * (35999.05029 - (1.537E-4 * jCent));
				eccentEarthOrbit = 0.016708634 - jCent *(4.2037E-5 + 1.537E-4 * jCent);
				sunEqCtr = Math.sin(Math.toRadians(geomMeanAnom)) * (1.914602 - jCent * (0.004817 + 1.4E-5 * jCent)) + Math.sin(Math.toRadians(2 * geomMeanAnom)) * (0.019993 - 1.01E-4 * jCent) + Math.sin(Math.toRadians(3 * geomMeanAnom)) * 2.89E-4;
				sunTrueLong = geomMeanLong + sunEqCtr;
				sunTrueAnom = geomMeanAnom + sunEqCtr;
				sunRadVector = (1.000001018 * (1 - eccentEarthOrbit * eccentEarthOrbit)) / (1 + eccentEarthOrbit * Math.cos(Math.toRadians(sunTrueAnom)));
				sunAppLong = sunTrueLong - 0.00569 - 0.00478 * Math.sin(Math.toRadians(125.04 - 1934.136 * jCent));
				meanObliqEclip = 23 + (26 + ((21.448 - jCent * (46.815 + jCent * (5.9E-4 - jCent * 0.001813)))) / 60) / 60;
				obliqCorr = meanObliqEclip + 0.00256 * Math.cos(Math.toRadians(125.04 - 1934.136 * jCent));
				sunRtAscen = Math.toDegrees(Math.atan2(Math.cos(Math.toRadians(obliqCorr)) * Math.sin(Math.toRadians(sunAppLong)), Math.cos(Math.toRadians(sunAppLong))));
				sunDecline = Math.toDegrees(Math.asin(Math.sin(Math.toRadians(obliqCorr)) * Math.sin(Math.toRadians(sunAppLong))));
				varY = Math.tan(Math.toRadians(obliqCorr / 2)) * Math.tan(Math.toRadians(obliqCorr / 2));
				eqOfTime = 4 * Math.toDegrees(varY * Math.sin(2 * Math.toRadians(geomMeanLong)) - 2 * eccentEarthOrbit * Math.sin(Math.toRadians(geomMeanAnom)) + 4 * eccentEarthOrbit * varY * Math.sin(Math.toRadians(geomMeanAnom)) * Math.cos(2 * Math.toRadians(geomMeanLong)) - 0.5 * varY * varY * Math.sin(4 * Math.toRadians(geomMeanLong)) - 1.25 * eccentEarthOrbit * eccentEarthOrbit * Math.sin(2 * Math.toRadians(geomMeanAnom)));
				haSunrise = Math.toDegrees(Math.acos(Math.cos(Math.toRadians(90.833)) / Math.cos(Math.toRadians(latitude)) * Math.cos(Math.toRadians(sunDecline)) - Math.tan(Math.toRadians(latitude)) * Math.tan(Math.toRadians(sunDecline))));
				solarNoon = (720 - 4 * longitude - eqOfTime + timeZone * 60) / 1440;
				sunriseTime = solarNoon - haSunrise * 4 / 1440;
				sunsetTime = solarNoon + haSunrise * 4 / 1440;
				sunlightDur = 8 * haSunrise;
				trueSolarTime = (timefraction * 1440 + eqOfTime + 4 * longitude - 60 * timeZone) % 1440;
				hourAngle = (trueSolarTime / 4 < 0 ? trueSolarTime / 4 + 180 : trueSolarTime / 4 - 180);
				solarZenithAngle = Math.toDegrees(Math.acos(Math.sin(Math.toRadians(latitude)) * Math.sin(Math.toRadians(sunDecline)) + Math.cos(Math.toRadians(latitude)) * Math.cos(Math.toRadians(sunDecline)) * Math.cos(Math.toRadians(hourAngle))));
				solarElevAngle = 90 - solarZenithAngle;
			}
			
			try {
				Thread.sleep(1000);
			}
			catch(Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	public String getTime() {

		/*int hour = now.get(Calendar.HOUR);
		int minutes = now.get(Calendar.MINUTE);
		int seconds = now.get(Calendar.SECOND);*/
		/*String h = "" + hour;
		String m = (minutes < 10 ? ":0" : ":") + minutes;
		String s = (seconds < 10 ? ":0" : ":") + seconds;
		String am_pm = (now.get(Calendar.AM_PM) == 0 ? " AM" : " PM");*/
		
		String date = now.getTime().toLocaleString();
		return(date);
        
	}
	
	private void initializeJulianDate() {
		year = now.get(Calendar.YEAR);
		month = now.get(Calendar.MONTH) + 1;
		date = now.get(Calendar.DATE);
		hour = now.get(Calendar.HOUR_OF_DAY);
		minute = now.get(Calendar.MINUTE);
		second = now.get(Calendar.SECOND);
		
		// Calculate Julian DateTime
		jA = Math.floor((14 - month) / 12);
		jY = year + 4800 - jA;
		jM = month + (12 * jA) - 3;
		jDN_noDate = Math.floor(((153 * jM) + 2) / 5) + (365 * jY) + Math.floor(jY / 4) - Math.floor(jY / 100) + Math.floor(jY / 400) - 32045;
		jD = jDN_noDate + date + ((hour - 12) / 24) + (minute / 1440) + (second / 86400);
	}
	
	private double getJulianDate() {
		// Calculate Julian DateTime
		//date = now.get(Calendar.DATE);
		hour = now.get(Calendar.HOUR_OF_DAY);
		minute = now.get(Calendar.MINUTE);
		second = now.get(Calendar.SECOND);
		timefraction = ((((hour * 60) + minute) * 60) + second) / (24 * 60 * 60);
		
		if(hour == 0) {
			// new day, reinitialize the other shit
			initializeJulianDate();
		}
		
		jD = jDN_noDate + date + ((hour - 12) / 24) + (minute / 1440) + (second / 86400);
        
		return jD - (timeZone / 24);
	}
	
	public double getJDN() {
		return jDN;
	}
	
	public double getJCent() {
		return jCent;
	}
	
	public double getGeomMeanLong() {
		return geomMeanLong;
	}
	
	public double getGeomMeanAnom() {
		return geomMeanAnom;
	}
	
	public double getEccentEarthOrbit() {
		return eccentEarthOrbit;
	}
	
	public double getSunEqCtr() {
		return sunEqCtr;
	}
	
	public double getSunTrueLong() {
		return sunTrueLong;
	}
	
	public double getSunTrueAnom() {
		return sunTrueAnom;
	}
	
	public double getSunAppLong() {
		return sunAppLong;
	}
	
	public double getSunRadVector() {
		return sunRadVector;
	}
	
	public double getMeanObliqEclip() {
		return meanObliqEclip;
	}
	
	public double getObliqCorr() {
		return obliqCorr;
	}
	
	public double getSunDecline() {
		return sunDecline;
	}
	
	public double getVarY() {
		return varY;
	}
	
	public double getEqOfTime() {
		return eqOfTime;
	}
	
	public double getHaSunrise() {
		return haSunrise;
	}
	
	public double getSolarNoon() {
		return solarNoon;
	}
	
	public double getSunriseTime() {
		return sunriseTime;
	}
	
	public double getSunsetTime() {
		return sunsetTime;
	}
	
	public double getSunlightDur() {
		return sunlightDur;
	}
	
	public double getTrueSolarTime() {
		return trueSolarTime;
	}
	
	public double getHourAngle() {
		return hourAngle;
	}
	
	public double getSolarZenithAngle() {
		return solarZenithAngle;
	}
	
	public double getSolarElevAngle() {
		return solarElevAngle;
	}
	
	public double getSecond() {
		return second;
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}
